package de.dhbw.ka.tit09.picsim.comm;

import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;

/**
 * class for serial communication
 * 
 * @author Stefan Unglaub
 */
public class CommSerial implements SerialPortEventListener {

	private CommPortIdentifier portId;
	private SerialPort serialPort;
	private OutputStream outputStream;
	private InputStream inputStream;
	private int[] InputBuffer;
	private int zaehler;
	private int bytesToRead;
	private boolean dataReceived;

	// private ArrayList<CommPortIdentifier> portList;
	// private BufferedReader inputReader;
	// private int availableBytes;
	// private int lowNibble;
	// private int highNibble;

	/**
	 * constructor for the CommSerial class
	 */
	public CommSerial() {
		bytesToRead = 5;
		InputBuffer = new int[bytesToRead];
		dataReceived = false;
	}

	/**
	 * @return received data
	 */
	public boolean getDataReceived() {
		return dataReceived;
	}

	/**
	 * clear the dataReceived variable
	 */
	public void clearDataReceived() {
		dataReceived = false;
	}

	/**
	 * @param chosenPort port-ID to use
	 */
	public void setPortId(CommPortIdentifier chosenPort) {
		portId = chosenPort;
	}

	/**
	 * @return ID of recently used Port
	 */
	public CommPortIdentifier getPortId() {
		return portId;
	}

	/**
	 * @return list of CommPortIdentifiers
	 */
	public List<CommPortIdentifier> getPortList() {
		@SuppressWarnings("unchecked")
		List<CommPortIdentifier> portList = Collections.list(CommPortIdentifier
				.getPortIdentifiers());
		return portList;
	}

	/**
	 * open port set parameters add listeners
	 */
	public void openPort() {
		try {
			serialPort = (SerialPort) portId.open("Hardwareansteuerung PIC",
					5000);
		} catch (PortInUseException e) {
		}

		try {
			serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
		} catch (UnsupportedCommOperationException e) {
		}

		try {
			serialPort.addEventListener(this);
			serialPort.notifyOnDataAvailable(true);
		} catch (Exception e) {
		}
	}

	/**
	 * close ports
	 */
	public void closePort() {
		serialPort.close();
	}

	/**
	 * @param data prepared data for output
	 * 
	 *            output data
	 */
	public void outputData(int[] data) {
		try {
			outputStream = serialPort.getOutputStream();
		} catch (IOException e) {
		}

		try {
			for (zaehler = 0; zaehler < data.length; zaehler++) {
				outputStream.write(data[zaehler]);
			}
		} catch (IOException e) {
		}
	}

	/**
	 * input PIC-View data
	 */
	private void inputData() {
		try {
			inputStream = serialPort.getInputStream();
		} catch (IOException e) {
		}

		try {
			for (int zaehler = 0; zaehler < bytesToRead; zaehler++) {
				InputBuffer[zaehler] = inputStream.read();
			}
			dataReceived = true;
		} catch (IOException e) {
		}
	}

	/**
	 * @return array of input bytes
	 */
	public int[] getInputBuffer() {
		return InputBuffer;
	}

	/**
	 * listener for receiving data
	 */
	public void serialEvent(SerialPortEvent event) {
		if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			if (dataReceived == false) {
				this.inputData();
			}
		}
	}
}
